﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Configuration.Install;

namespace HybridWindowsService
{
    public class HybridServiceBase : ServiceBase
    {
        /// <summary>
        /// Simulated service start, executes code in OnStart method
        /// </summary>
        /// <param name="args"></param>
        public void Start(string[] args)
        {
            this.OnStart(args);
        }
        public static void Run(HybridServiceBase[] services)
        {

            if (!Environment.UserInteractive)
            {
                ServiceBase.Run(services);
            }
            else
            {
               List<string> args = new List<string>(Environment.GetCommandLineArgs());
                if (args.Contains("-install"))
                {
                    foreach (var svc in services)
                    {
                        if (!IsServiceInstalled(svc.ServiceName))
                        {
                            InstallService(svc.ServiceName);
                        }
                        Console.WriteLine(string.Format("Installed service {0}", svc.ServiceName));
                    }
                    Application.Exit();
                }
                else if (args.Contains("-uninstall"))
                {
                    foreach (var svc in services)
                    {
                        if (!IsServiceInstalled(svc.ServiceName))
                        {
                            UninstallService(svc.ServiceName);
                        }
                     Console.WriteLine(string.Format("Uninstalled service {0}", svc.ServiceName));
                   }
                    Application.Exit();
                   
                }
                else
                {
                     Application.EnableVisualStyles();
                        Application.SetCompatibleTextRenderingDefault(false);
                       HiddenMain main = new HiddenMain();
                    foreach (var svc in services)
                    {
                        main.InitializeService(svc, Environment.GetCommandLineArgs());
                    }
                    try
                    {
                        Application.Run(main);
                        if (main.ExitCode != 0)
                        {
                            System.Environment.ExitCode=main.ExitCode;
                            Application.Exit();
                        }
                    }
                    catch (System.Security.SecurityException)	//Only catch security exceptions
                    {
                        MessageBox.Show("A .NET security error has occured, please check your .NET security settings in the Control Panel", "Security Error");
                    }
                    catch (Exception ex)
                    {
#if DEBUG
                    MessageBox.Show(ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace, "Debug Message");
#else
                        MessageBox.Show("An error has occured in the application and will now be closed");
#endif
                    }

                }
            }
        }
        private static bool IsServiceInstalled(string serviceName)
        {

            using (ServiceController serviceController = new ServiceController(serviceName))
            {

                try
                {

                    ServiceControllerStatus status = serviceController.Status;

                }

                catch (InvalidOperationException)
                {

                    return false;

                }

                catch (Exception ex)
                {

                    EventLog.WriteEntry("ServiceManager",
                                        ex.ToString(), EventLogEntryType.Error);

                    return false;

                }

                return true;

            }

        }


        protected static void InstallService(string serviceName)
        {

            if (IsServiceInstalled(serviceName))

                return;

            try
            {

                string[] commandLine = new string[0];

               
                IDictionary mySavedState = new Hashtable();

                AssemblyInstaller installer = GetAssemblyInstaller(commandLine);

                try
                {

                    installer.Install(mySavedState);

                    installer.Commit(mySavedState);

                }

                catch (Exception ex)
                {

                    installer.Rollback(mySavedState);

                    EventLog.WriteEntry("ServiceManager",
                                        ex.ToString(), EventLogEntryType.Error);

                }

            }

            catch (Exception ex)
            {

                EventLog.WriteEntry("ServiceManager", ex.ToString());

            }

        }



        private static AssemblyInstaller GetAssemblyInstaller(string[] commandLine)
        {

            AssemblyInstaller installer = new AssemblyInstaller();

            installer.Path = Environment.GetCommandLineArgs()[0];

            installer.CommandLine = commandLine;

            installer.UseNewContext = true;

            return installer;

        }



        private static void UninstallService(string serviceName)
        {

            if (!IsServiceInstalled(serviceName))

                return;

            string[] commandLine = new string[0];

           
            IDictionary mySavedState = new Hashtable();

            mySavedState.Clear();

            AssemblyInstaller installer = GetAssemblyInstaller(commandLine);

            try
            {

                installer.Uninstall(mySavedState);

            }

            catch (Exception ex)
            {

                EventLog.WriteEntry("ServiceManager",
                                    ex.ToString(), EventLogEntryType.Error);

            }

        }

 
    }
}
